package com.neo.controller;

import com.neo.config.ConfirmConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;

/**
 * @ClassName: ProducerController
 * @Title: springboot-rabbitmq
 * @Package: com.neo.controller
 * @Description:
 * @Author: Kisen
 * @Date: 2021/9/27 21:57
 */

@Slf4j
@RestController
@RequestMapping("/confirm")
public class ProducerController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 依赖注入rabbitTemplat之后再设置它的回调对象
     * Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
     */
    @PostConstruct
    public void init() {
        /**
         * 交换机不管是否收到消息的一个回调方法
         * 1.CorrelationData 消息相关数据
         * 2.ack 交换机是否收到消息
         * 3.cause 未收到消息的原因
         */
        RabbitTemplate.ConfirmCallback confirmCallback = (correlationData, ack, cause) -> {
            String id = correlationData != null ? correlationData.getId() : "";
            if (ack) {
                log.info("交换机已经接收到id为：{}的消息", id);
            } else {
                log.info("交换机未接收到id为：{}的消息，由于原因：{}", id, cause);
            }
        };
        rabbitTemplate.setConfirmCallback(confirmCallback);

        /**
         * 消息回退：只有当消息传递过程种不可达目的地时才将消息返回给生产者
         */
        RabbitTemplate.ReturnsCallback returnsCallback = returned -> {
            log.error("消息：{}被交换机退回，退回原因：{}，交换机是：{}，路由key：{}",
                    new String(returned.getMessage().getBody()), returned.getReplyText(),
                    returned.getExchange(), returned.getRoutingKey());
        };
        rabbitTemplate.setReturnsCallback(returnsCallback);
    }

    @GetMapping("/sendMessage/{message}")
    public void sendMessage(@PathVariable String message) {
        // 指定消息id为1
        CorrelationData correlationData1 = new CorrelationData("1");
        String routingKey = "key1";
        rabbitTemplate.convertAndSend(ConfirmConfig.CONFIRM_EXCHANGE_NAME, routingKey,
                message + routingKey, correlationData1);
        log.info("发送消息内容：{}", message);

        CorrelationData correlationData2 = new CorrelationData("2");
        routingKey = "key2";
        rabbitTemplate.convertAndSend(ConfirmConfig.CONFIRM_EXCHANGE_NAME, routingKey,
                message + routingKey, correlationData2);
        log.info("发送消息内容：{}", message);
    }
}
